// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "air105_cache.h"


void CACHE_Init(CACHE_TypeDef *Cache, CACHE_InitTypeDef *CACHE_InitStruct)
{
	int i;
	
	if (CACHE_InitStruct->aes_enable == ENABLE)
	{
		assert_param(IS_CACHE_ENCRYPT_MODE(CACHE_InitStruct->encrypt_mode));		
		
		for (i = 0; i < 5000; i++)
		{
			if (Cache->CACHE_CS & CACHE_IS_BUSY)	//cache正在从Flash中取指
			{
				continue;
			}
			break;
		}
		Cache->CACHE_CONFIG &= 0xFFFFFF00;//关闭bypass
		
		Cache->CACHE_CS = (Cache->CACHE_CS & ~0x10000000) | (CACHE_InitStruct->algorithm << CHCHE_ALGORITHM_SET_POS);	//选择解密算法		
		Cache->CACHE_CS = (Cache->CACHE_CS & ~0xFF) | CACHE_KEY_GEN;	//密钥生成模式

		Cache->CACHE_I3 = CACHE_InitStruct->I[3];
		Cache->CACHE_I2 = CACHE_InitStruct->I[2];   
		Cache->CACHE_I1 = CACHE_InitStruct->I[1];       
		Cache->CACHE_I0 = CACHE_InitStruct->I[0];   

		Cache->CACHE_K3 = CACHE_InitStruct->K[3];
		Cache->CACHE_K2 = CACHE_InitStruct->K[2];   
		Cache->CACHE_K1 = CACHE_InitStruct->K[1];       
		Cache->CACHE_K0 = CACHE_InitStruct->K[0];             

		Cache->CACHE_CS |= CACHE_KEY_GEN_START; 
		for (i = 0; i < 10000; i++)
		{
			if((Cache->CACHE_CS & CACHE_KEY_GEN_START) == 0)
			{
			    Cache->CACHE_CS &= 0x10000000;
			    break;
			}   
		} 
		Cache->CACHE_CS &= 0x10000000;
		Cache->CACHE_CONFIG = (Cache->CACHE_CONFIG & ~0xFF00FFFF);
		
		if (CACHE_Encrypt_Mode_Zone == CACHE_InitStruct->encrypt_mode)
		{
			uint32_t saddr_align = CACHE_InitStruct->encrypt_saddr & ~(CACHE_PARTICLE_SIZE-1);
			uint32_t eaddr_align = CACHE_InitStruct->encrypt_eaddr & ~(CACHE_PARTICLE_SIZE-1);	
			
			assert_param(IS_CACHE_ADDR_VALID(saddr_align));
			assert_param(IS_CACHE_ADDR_VALID(eaddr_align));
			assert_param(saddr_align <= eaddr_align);
			
			Cache->CACHE_SADDR = saddr_align;
			Cache->CACHE_EADDR = eaddr_align;
			Cache->CACHE_CONFIG = (Cache->CACHE_CONFIG & ~0xFF000000) | CACHE_ZONE_ENCRYPT;
		}
	}
	else
	{
		Cache->CACHE_CONFIG = (Cache->CACHE_CONFIG & ~0xFF00FFFF) | CACHE_AES_BYPASS;
	}
	
}

/*clean cache flash data/instructions*/
void CACHE_Clean(CACHE_TypeDef *Cache, CACHE_InitTypeDef *CACHE_InitStruct)
{
	uint32_t i ,address;
	address = (CACHE_InitStruct->Address & ~(CACHE_PARTICLE_SIZE-1)) & CACHE_ADDRESS_MAX;
	
	for (i = 0; i < CACHE_InitStruct->size; i += CACHE_PARTICLE_SIZE)
	{
		Cache->CACHE_REF = (address + i);
		Cache->CACHE_REF |= CACHE_REFRESH;
		while ((Cache->CACHE_REF & CACHE_REFRESH));	
	}
}

void CACHE_CleanAll(CACHE_TypeDef *Cache)
{
	while (Cache->CACHE_CS & CACHE_IS_BUSY);
	
	Cache->CACHE_REF = CACHE_REFRESH_ALLTAG;
	Cache->CACHE_REF |= CACHE_REFRESH;
	while ((Cache->CACHE_REF & CACHE_REFRESH));	
}
